<?php
/**
 * Created by : PhpStorm
 * User: godjarvis
 * Date: 2020/8/11
 * Time: 17:07
 */

namespace App\Model\Dao\DangKou;


use App\Bucket\Utils\MyToolkit;
use App\Http\Requests\Product\ProductExtraPricePo;
use App\Http\Requests\Product\ProductPricePo;
use App\Model\Entity\DangKou\ProductItemPromotion;
use App\Model\Entity\DangKou\ProductPricingSeckill;
use App\Model\Entity\DangKou\ProductPricingSpecial;
use App\Model\Entity\DangKou\Promotion;
use Fresh\Annotation\ConnectionField;
use Fresh\Mvc\Model\Dao;
use Fresh\Weird\QueryBuilder;

class PromotionDao extends Dao
{
    /**
     * @ConnectionField(name="dangkou")
     */
    public function getPromotionPids(array $ids)
    {
        $rows = $this->expr()
            ->inWhere('id', $ids)
            ->inWhere('type', [Promotion::TYPE_MINUS_AMOUNT, Promotion::TYPE_REDUCE_PRICE])
            ->from(Promotion::class)
            ->query()
            ->find();
        if (!$rows) {
            $pids = [];
        } else {
            $pids = [];
            foreach ($rows as $row) {
                $data = unserialize($row['data']);
                if ($row['type'] == Promotion::TYPE_MINUS_AMOUNT) {
                    $pids = $data['product'];
                }
                if ($data['price'] && is_array($data['price'])) {
                    $pids = array_merge($pids, array_keys($data['price']));
                }
            }
        }

        return $pids;
    }


    public function getTimeCondition()
    {
        $now = time();
        return '(`date_start` >= 0 AND `date_start` <= ' . $now . ') AND (`date_end` >= ' . $now . ' OR `date_end` = 0)';
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getSecKillProductPids()
    {
        $this->createQueryBuilder()
            ->from(ProductPricingSeckill::class)
            ->where($this->getTimeCondition())
            ->where('date_audit>0')
            ->where('disabled=0')
            ->query()
            ->lists('pid');
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getExtraPrices($pid)
    {
        $promotions = $this->getPromotionProductPrices();
        $specials = $this->getSpecialProductPrices($pid);
        $seckills = $this->getSeckillProductPrices($pid);

        $row = null;
        if ($seckills[$pid]) {
            $row = new ProductExtraPricePo($seckills[$pid], ProductExtraPricePo::TYPE_SECKILL);
        } else if ($specials[$pid]) {
            $row = new ProductExtraPricePo($specials[$pid], ProductExtraPricePo::TYPE_SPECIAL);
        } else if ($promotions[$pid]) {
            $row = new ProductExtraPricePo($promotions[$pid], ProductExtraPricePo::TYPE_PROMOTION);
        }
        $result[$pid] = $row;

        return $result;
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getPromotionProductPrices()
    {
        $items = [];
        $list = $this->getPromotions();
        foreach ($list as $v) {
            if ($v['type'] != Promotion::TYPE_REDUCE_PRICE) {
                continue;
            }
            $data = unserialize($v['data']);
            foreach ($data['price'] as $pid => $price) {
                $items[$pid][MyToolkit::convert2float($price, 2)] = $v['id'];
            }
        }

        $result = [];
        foreach ($items as $pid => $v) {
            $price = min(array_keys($v));
            $result[$pid] = new ProductPricePo($v[$price], $price);
        }

        return $result;
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getSpecialProductPrices($pid)
    {
        $list = $this->createQueryBuilder()
            ->from(ProductPricingSpecial::class)
            ->where('pid=?', $pid)
            ->where($this->getTimeCondition())
            ->where('date_audit>0')
            ->where('price_step_cycle>0')
            ->where('disabled=0')
            ->orderBy('date_start asc, id asc')
            ->query()
            ->find();

        $result = [];
        foreach ($list as $v) {
            $price = $this->getPriceNow($v, time());
            $result[$v['pid']] = new ProductPricePo($v['id'], $price);
        }
        return $result;
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getSeckillProductPrices($pid)
    {
        $list = $this->createQueryBuilder()
            ->from(ProductPricingSeckill::class)
            ->where('pid=?', $pid)
            ->where($this->getTimeCondition())
            ->where('date_audit>0')
            ->where('disabled=0')
            ->orderBy('date_start asc, id asc')
            ->query()
            ->find();

        $result = [];
        foreach ($list as $v) {
            $result[$v['pid']] = new ProductPricePo($v['id'], $v['price']);
        }
        return $result;
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getPromotions()
    {
        return $this->createQueryBuilder()
            ->from(Promotion::class)
            ->where($this->getTimeCondition())
            ->where('date_approved>0')
            ->where('useable=0 OR useable>used')
            ->where('disabled=0')
            ->orderBy('date_start asc')
            ->query()
            ->find();
    }

    private function getPriceNow($row, $time)
    {
        $cycle = floor(($time - $row['date_start']) / 86400) / $row['price_step_cycle'];
        if ($cycle > 0) {
            $price = 0;
            if ($row['price_step'] > 0) {
                $price = round(bcsub($row['price_start'], bcmul($row['price_step'], $cycle)));
            } elseif ($row['price_step_rate'] > 0 && $row['price_step_rate'] < 1) {
                $price = round(bcmul($row['price_start'], bcpow(bcsub(1, $row['price_step_rate']), $cycle)));
            }
            $price = max($row['price_end'], $price);
        } else {
            $price = $row['price_start'];
        }
        return $price;
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getPromotion($id)
    {
        return $this->createQueryBuilder()
            ->from(Promotion::class)
            ->where('id=?', $id)
            ->query()
            ->findFirst();
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getSeckill($id)
    {
        return $this->createQueryBuilder()
            ->from(ProductPricingSeckill::class)
            ->where('id=?', $id)
            ->query()
            ->findFirst();
    }

    /**
     * @ConnectionField(name="dangkou")
     */
    public function getSpecial($id)
    {
        return $this->createQueryBuilder()
            ->from(ProductPricingSpecial::class)
            ->where('id=?', $id)
            ->query()
            ->findFirst();
    }
}